// *********************************************************************************
// Project Name : wrr_arbiter
// Author       : xfsong
// Email        : 1293993416@qq.com
// Create Time  : 2024-05-07
// File Name    : .v
// Module Name  :
// Called By    :
// Abstract     :
//
// 
// *********************************************************************************
// Modification History:
// Date         By              Version                 Change Description
// -----------------------------------------------------------------------
// 2024-05-07    Macro           1.0                     Original
//  
// *********************************************************************************

module wrr_arbiter #(
 parameter N = 8, BIT0_WEIGHT = 8, BIT1_WEIGHT = 7, BIT2_WEIGHT = 6, BIT3_WEIGHT = 5, BIT4_WEIGHT = 4, 
 parameter        BIT5_WEIGHT = 3, BIT6_WEIGHT = 2, BIT7_WEIGHT = 1  //weight range:1~15
)(
input         clk,
input         rst_n,
input [N-1:0] req,
output[N-1:0] grant
);

logic [N-1:0] req_masked;
logic [N-1:0] mask_higher_pri_reqs;
logic [N-1:0] grant_masked;
logic [N-1:0] unmask_higher_pri_reqs;
logic [N-1:0] grant_unmasked;
logic no_req_masked;
logic [N-1:0] pointer_reg;
logic mask_refresh;
logic [3:0] cnt0, cnt1, cnt2, cnt3, cnt4, cnt5, cnt6, cnt7;

// Simple priority arbitration for masked portion
assign req_masked = req & pointer_reg;
assign mask_higher_pri_reqs[N-1:1] = mask_higher_pri_reqs[N-2: 0] | req_masked[N-2:0];
assign mask_higher_pri_reqs[0] = 1'b0;
assign grant_masked[N-1:0] = req_masked[N-1:0] & ~mask_higher_pri_reqs[N-1:0];

// Simple priority arbitration for unmasked portion
assign unmask_higher_pri_reqs[N-1:1] = unmask_higher_pri_reqs[N-2:0] | req[N-2:0];
assign unmask_higher_pri_reqs[0] = 1'b0;
assign grant_unmasked[N-1:0] = req[N-1:0] & ~unmask_higher_pri_reqs[N-1:0];

// Use grant_masked if there is any there, otherwise use grant_unmasked. 
assign no_req_masked = ~(|req_masked);
assign grant = ({N{no_req_masked}} & grant_unmasked) | grant_masked;


// Pointer update
always @ (posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    pointer_reg <= {N{1'b1}};
  end 
  else if(pointer_reg == {N{1'b0}})begin
      if(|req)
          pointer_reg <= {N{1'b1}};
  end
  else if(mask_refresh)begin
    if (|req_masked) begin // Which arbiter was used?
      pointer_reg <= mask_higher_pri_reqs;
    end else begin
      if (|req) // Only update if there's a req 
        pointer_reg <= unmask_higher_pri_reqs;
    end
  end
  else
      pointer_reg <= pointer_reg;
end

//pointer refresh condition
//assign mask_refresh = ~(|cnt0) | ~(|cnt1) | ~(|cnt2) | ~(|cnt3) | ~(|cnt4) | ~(|cnt5) | ~(|cnt6) | ~(|cnt7);
assign mask_refresh = (cnt0 == 8'd1 && grant == 8'd1) || (cnt1 == 8'd1 && grant == 8'd2) || (cnt2 == 8'd1 && grant == 8'd4) || (cnt3 == 8'd1 && grant == 8'd8) || (cnt4 == 8'd1 && grant == 8'd16) || (cnt5 == 8'd1 && grant == 8'd32) || (cnt6 == 8'd1 && grant == 8'd64) || (cnt7 == 8'd1 && grant == 8'd128);

//grant-counter bit-0
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt0 <= BIT0_WEIGHT;
    else begin
        if(no_req_masked)
            cnt0 <= BIT0_WEIGHT;
        else if(grant == 8'b0000_0001)
            cnt0 <= cnt0 - 1'b1;
    end
end
//grant-counter bit-1
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt1 <= BIT1_WEIGHT;
    else begin
        if(no_req_masked)
            cnt1 <= BIT1_WEIGHT;
        else if(grant == 8'b0000_0010)
            cnt1 <= cnt1 - 1'b1;
    end
end
//grant-counter bit-2
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt2 <= BIT2_WEIGHT;
    else begin
        if(no_req_masked)
            cnt2 <= BIT2_WEIGHT;
        else if(grant == 8'b0000_0100)
            cnt2 <= cnt2 - 1'b1;
    end
end
//grant-counter bit-3
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt3 <= BIT3_WEIGHT;
    else begin
        if(no_req_masked)
            cnt3 <= BIT3_WEIGHT;
        else if(grant == 8'b0000_1000)
            cnt3 <= cnt3 - 1'b1;
    end
end
//grant-counter bit-4
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt4 <= BIT4_WEIGHT;
    else begin
        if(no_req_masked)
            cnt4 <= BIT4_WEIGHT;
        else if(grant == 8'b0001_0000)
            cnt4 <= cnt4 - 1'b1;
    end
end
//grant-counter bit-5
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt5 <= BIT5_WEIGHT;
    else begin
        if(no_req_masked)
            cnt5 <= BIT5_WEIGHT;
        else if(grant == 8'b0010_0000)
            cnt5 <= cnt5 - 1'b1;
    end
end
//grant-counter bit-6
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt6 <= BIT6_WEIGHT;
    else begin
        if(no_req_masked)
            cnt6 <= BIT6_WEIGHT;
        else if(grant == 8'b0100_0000)
            cnt6 <= cnt6 - 1'b1;
    end
end
//grant-counter bit-7
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt7 <= BIT7_WEIGHT;
    else begin
        if(no_req_masked)
            cnt7 <= BIT7_WEIGHT;
        else if(grant == 8'b1000_0000)
            cnt7 <= cnt7 - 1'b1;
    end
end

endmodule
